﻿/*using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;

namespace WebPALTT.Lib
{
    public interface IActionItem : ISerializable
    {
        String Name { get; set; }
        ActionType ActionType { get; }
        ActionResults Results { get; set; }

        string[] Validate();
    }

    [Serializable()]
    public abstract class ActionItem : ISerializable
    {
        String mName;
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get; }

        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        string[] Validate();
    }

    public enum ActionType { WebRequest, Script, Sleep, If, Loop, Variable }

    [Serializable()]
    public class ActionItem_WebRequest : ActionItem
    {        
        String mName;        
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get { return ActionType.WebRequest; } }
        
        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        String mMethod;
        Uri mUri;
        String mHttpVersion;
        KeyValuePair<String, String>[] mHeaders;
        String mContent;

        #region Properties
        /// <summary>
        /// Gets or set the Http method (e.g. GET, POST, ...).
        /// </summary>
        public String Method
        {
            get { return mMethod; }
            set { mMethod = value; }
        }

        /// <summary>
        /// Gets or set the Uri of the request.
        /// </summary>
        public Uri Uri
        {
            get { return mUri; }
            set { mUri = value; }
        }

        /// <summary>
        /// Gets or set the http protocol version (Only 1.0 and 1.1 are supported).
        /// </summary>
        public String HttpVersion
        {
            get { return mHttpVersion; }
            set { mHttpVersion = value; }
        }

        /// <summary>
        /// Gets or set the array of http headers for the request as key-value pairs.
        /// </summary>
        public KeyValuePair<String, String>[] Headers
        {
            get { return mHeaders; }
            set { mHeaders = value; }
        }

        /// <summary>
        /// Gets or set the body of the http request (only available for POST requests). 
        /// </summary>        
        [Editor(typeof(System.ComponentModel.Design.MultilineStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public String Content
        {
            get { return mContent; }
            set { mContent = value; }
        }
        #endregion

        /// <summary>
        /// Creates a new web request action item.
        /// </summary>
        /// <param name="method">The method for the request</param>
        /// <param name="uri">The Uri of the request</param>
        /// <param name="httpVersion">The http protocol version</param>
        /// <param name="headers">List of headers for the request</param>
        /// <param name="content">The body of the request</param>
        public ActionItem_WebRequest(String name, String method, Uri uri, String httpVersion, KeyValuePair<String, String>[] headers, String content)
        {
            mName = name;
            mMethod = method;
            mUri = uri;
            mHttpVersion = httpVersion;
            mHeaders = headers;
            mContent = content;
        }

        public ActionItem_WebRequest(String name) : this(name, "GET", null, "1.0", new KeyValuePair<string, string>[] { }, "") { }        

        public ActionItem_WebRequest(SerializationInfo info, StreamingContext ctxt)
        {
            mName = (string)info.GetValue("Name", typeof(string));
            mMethod = (string)info.GetValue("Method", typeof(string));
            mUri = (Uri)info.GetValue("Uri", typeof(Uri));
            mHttpVersion = (string)info.GetValue("HttpVersion", typeof(string));
            mHeaders = (KeyValuePair<String, String>[])info.GetValue("Headers", typeof(KeyValuePair<String, String>[]));
            mContent = (string)info.GetValue("Content", typeof(string));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", mName);
            info.AddValue("Method", mMethod);
            info.AddValue("Uri", mUri);
            info.AddValue("HttpVersion", mHttpVersion);
            info.AddValue("Headers", mHeaders);
            info.AddValue("Content", mContent);
        }

        public string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            return errors.ToArray();
        }
    }

    [Serializable()]
    public class ActionItem_Script : IActionItem
    {
        String mName;
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get { return ActionType.Script; } }

        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        List<string> mCompileParameters;
        List<string> mUsingStatements;
        string mMethod;
        string mCode;

        [Editor(@"System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
        public List<string> CompileParameters { get { return mCompileParameters; } }

        [Editor(@"System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
        public List<string> UsingStatements { get { return mUsingStatements; } }
        
        [DescriptionAttribute("The name of the method to call when running script.")]
        public string StartMethod { get { return mMethod; } set { mMethod = value; } }
        
        [BrowsableAttribute(false)]
        public string Code { get { return mCode; } set { mCode = value; } }

        public ActionItem_Script(String name) : this(name, null, null, "", "") { }

        public ActionItem_Script(String name, string[] parameters, string[] usingstatements, string startmethod, string code)
        {
            mName = name;
            mCompileParameters = new List<string> { };
            mUsingStatements = new List<string> { };
            if(parameters != null)
                mCompileParameters.AddRange(parameters);
            if (usingstatements != null)
                mUsingStatements.AddRange(usingstatements);
            mMethod = startmethod;
            mCode = code;
        }

        public ActionItem_Script(SerializationInfo info, StreamingContext ctxt)
        {
            mName = (string)info.GetValue("Name", typeof(string));
            mCompileParameters = (List<string>)info.GetValue("Parameters", typeof(List<string>));
            mUsingStatements = (List<string>)info.GetValue("UsingStatements", typeof(List<string>));
            mMethod = (string)info.GetValue("Method", typeof(string));
            mCode = (string)info.GetValue("Code", typeof(string));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", mName);
            info.AddValue("Parameters", mCompileParameters);
            info.AddValue("UsingStatements", mUsingStatements);
            info.AddValue("Method", mMethod);
            info.AddValue("Code", mCode);
        }

        public string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            if (StartMethod.IndexOfAny(new char[] { ' ', '(', ')', '[', ']', '{', '}', ';', ':', '.', ',', '\\', '/' }) > -1)
                errors.Add("Error: action[" + Name + "(" + ActionType + ")].StartMethod contains invalid characters.");

            return errors.ToArray();
        }
    }

    [Serializable()]
    public class ActionItem_Sleep : IActionItem
    {
        String mName;
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get { return ActionType.Sleep; } }

        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        int mDuration;
        bool mRandom;
        int mMax;
        int mMin;

        [DescriptionAttribute("Sleep duration in milliseconds.")]
        public int Duration { get { return mDuration; } set { mDuration = value; } }
        [DescriptionAttribute("Selects a sleep duration minimum and maximum duration.")]
        public bool IsRandom { get { return mRandom; } set { mRandom = value; } }
        [DescriptionAttribute("Minimum sleep duration in milliseconds. \r\n(only used if IsRandom is true)")]
        public int Min { get { return mMin; } set { mMin = value; } }
        [DescriptionAttribute("Maximum sleep duration in milliseconds. \r\n(only used if IsRandom is true)")]
        public int Max { get { return mMax; } set { mMax = value; } }

        /// <summary>
        /// Creates a new sleep action of 0 ms.
        /// </summary>
        /// <param name="name"></param>
        public ActionItem_Sleep(String name) : this(name, 0) { }

        /// <summary>
        /// Creates a new sleep action.
        /// </summary>
        /// <param name="name">name of the action</param>
        /// <param name="duration">duration in milliseconds</param>
        public ActionItem_Sleep(String name, int duration)
        {            
            if (duration < 0)
                throw new Exception("Parameter is incorrect: Sleep value cannot be less than zero.");
            mName = name;
            mDuration = duration;
            mRandom = false;
            mMin = 0;
            mMax = 0;
        }

        /// <summary>
        /// Creates a new sleep action with a random sleep time.
        /// </summary>
        /// <param name="name">name of the action</param>
        /// <param name="min">minimum sleep time in milliseconds</param>
        /// <param name="max">maximum sleep time in milliseconds</param>
        public ActionItem_Sleep(String name, int min, int max)
        {
            if (min < 0)
                throw new Exception("Parameter is incorrect: Sleep value cannot be less than zero.");
            if (max < min)
                throw new Exception("Parameter is incorrect: Maximum value must be greater than minimum.");
            mName = name;
            mDuration = 0;
            mRandom = true;
            mMin = min;
            mMax = max;
        }

        public ActionItem_Sleep(SerializationInfo info, StreamingContext ctxt)
        {
            mName = (string)info.GetValue("Name", typeof(string));
            mDuration = (int)info.GetValue("Duration", typeof(int));
            mRandom = (bool)info.GetValue("Random", typeof(bool));
            mMin = (int)info.GetValue("Min", typeof(int));
            mMax = (int)info.GetValue("Max", typeof(int));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", mName);
            info.AddValue("Duration", mDuration);
            info.AddValue("Random", mRandom);
            info.AddValue("Min", mMin);
            info.AddValue("Max", mMax);
        }

        public int GetSleepDuration()
        {
            if (this.IsRandom)
                return (new Random().Next(mMin, mMax));
            return mDuration;
        }

        public string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            if (IsRandom)
            {
                if (Max < Min)
                    errors.Add("Error: action[" + Name + "(" + ActionType + ")] - Maximum sleep value must be greater than or equal to minimum.");
                if (Max < 0 || Min < 0)
                    errors.Add("Error: action[" + Name + "(" + ActionType + ")] - Maximum and minimum sleep values must be greater than or equal to zero.");
            }
            else
                if (Duration < 0)
                    errors.Add("Error: action[" + Name + "(" + ActionType + ")]. - Sleep duration must be greater than or equal to zero.");

            return errors.ToArray();
        }
    }

    [Serializable()]
    public class ActionItem_Loop : IActionItem
    {
        String mName;
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get { return ActionType.Loop; } }

        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        int mLoopCount;
        ActionItemCollection mActions;

        [DescriptionAttribute("Number of times to loop.")]
        public int Count { get { return mLoopCount; } set { mLoopCount = value; } }
        [BrowsableAttribute(false)]
        public ActionItemCollection Actions { get { return mActions; } set { mActions = value; } }

        public ActionItem_Loop(string name) : this(name, 0, null) { }

        public ActionItem_Loop(string name, int loopcount, ActionItemCollection actions)
        {
            mName = name;
            mLoopCount = loopcount;
            if (actions != null)
                mActions = actions;
            else
                mActions = new ActionItemCollection();
        }

        public ActionItem_Loop(SerializationInfo info, StreamingContext ctxt)
        {
            mName = (string)info.GetValue("Name", typeof(string));
            mLoopCount = (int)info.GetValue("LoopCount", typeof(int));
            mActions = (ActionItemCollection)info.GetValue("Actions", typeof(ActionItemCollection));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", mName);
            info.AddValue("LoopCount", mLoopCount);
            info.AddValue("Actions", mActions);
        }

        public string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            if (Actions.Count == 0)
                errors.Add("Warning: action[" + Name + "(" + ActionType + ")]. - Loop action doesn't contain any sub actions");
            foreach (IActionItem action in Actions)
                errors.AddRange(action.Validate());

            return errors.ToArray();
        }
    }

    [Serializable()]
    public class ActionItem_If : IActionItem
    {
        String mName;
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get { return ActionType.If; } }

        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        string mCondition;
        ActionItemCollection mThenActions;
        ActionItemCollection mElseActions;

        [DescriptionAttribute("Condition to evaluate at runtime.")]
        [Editor(typeof(System.ComponentModel.Design.MultilineStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public string Condition { get { return mCondition; } set { mCondition = value; } }
        [BrowsableAttribute(false)]
        public ActionItemCollection ThenActions { get { return mThenActions; } set { mThenActions = value; } }
        [BrowsableAttribute(false)]
        public ActionItemCollection ElseActions { get { return mElseActions; } set { mElseActions = value; } }

        public ActionItem_If(string name) : this(name, "true", null, null) { }

        public ActionItem_If(string name, string condition, ActionItemCollection thenactions, ActionItemCollection elseactions)
        {
            mName = name;
            mCondition = condition;
            mThenActions = thenactions == null ? new ActionItemCollection() : thenactions;
            mElseActions = elseactions == null ? new ActionItemCollection() : elseactions;
        }

        public ActionItem_If(SerializationInfo info, StreamingContext ctxt)
        {
            mName = (string)info.GetValue("Name", typeof(string));
            mCondition = (string)info.GetValue("Condition", typeof(string));
            mThenActions = (ActionItemCollection)info.GetValue("ThenActions", typeof(ActionItemCollection));
            mElseActions = (ActionItemCollection)info.GetValue("ElseActions", typeof(ActionItemCollection)); 
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", mName);
            info.AddValue("Condition", mCondition);
            info.AddValue("ThenActions", mThenActions);
            info.AddValue("ElseActions", mElseActions);
        }

        public string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");
            if (Name.IndexOfAny(new char[] { ' ', '(', ')', '[', ']', '{', '}', ';', ':', '.', ',', '\\', '/' }) > -1)
                errors.Add("Error: action[" + Name + "(" + ActionType + ")].Name contains invalid characters.");

            if (ThenActions.Count == 0 && ElseActions.Count == 0)
                errors.Add("Warning: action[" + Name + "(" + ActionType + ")]. - Conditional action doesn't contain any sub actions");
            foreach (IActionItem action in ThenActions)
                errors.AddRange(action.Validate());
            foreach (IActionItem action in ElseActions)
                errors.AddRange(action.Validate());

            return errors.ToArray();
        }
    }

    [Serializable()]
    public class ActionItem_Variable : IActionItem
    {
        String mName;
        [CategoryAttribute("Action Properties")]
        public String Name { get { return mName; } set { mName = value; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public ActionType ActionType { get { return ActionType.Variable; } }

        ActionResults mResults;
        [ReadOnlyAttribute(true), BrowsableAttribute(false)]
        public ActionResults Results { get { return mResults; } set { mResults = value; } }

        string mType;
        bool mStatic = false;
        string mValue = null;

        [DescriptionAttribute("The type of the variable. (supported types: Int16, Int32, Int64, float, double, bool, string )")]
        public string Type { get { return mType; } set { mType = value; } }
        [DescriptionAttribute("Indicates whether the variable is static.")]
        public bool IsStatic { get { return mStatic; } set { mStatic = value; } }
        [DescriptionAttribute("The value of the variable")]
        public string Value { get { return mValue; } set { mValue = value; } }

        public ActionItem_Variable(string name) : this(name, "string", false, null) { }

        public ActionItem_Variable(string name, string type, bool isStatic, string value)
        {
            mName = name;
            mType = type;
            mStatic = isStatic;
            mValue = value;
        }

        public ActionItem_Variable(SerializationInfo info, StreamingContext ctxt)
        {
            mName = (string)info.GetValue("Name", typeof(string));
            mType = (string)info.GetValue("Type", typeof(string));
            mStatic = (bool)info.GetValue("Static", typeof(bool));
            mValue = (string)info.GetValue("Value", typeof(string));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", mName);
            info.AddValue("Type", mType);
            info.AddValue("Static", mStatic);
            info.AddValue("Value", mValue);
        }

        public string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions") || Name.Equals("Then"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            if (Name.IndexOfAny(new char[] { ' ', '(', ')', '[', ']', '{', '}', ';', ':', '.', ',', '\\', '/' }) > -1)
                errors.Add("Error: action[" + Name + "(" + ActionType + ")].Name contains invalid characters.");

            return errors.ToArray();
        }
    }

    class ActionItem_HttpRequest
    {
        private HttpWebRequest mRequest;
        private String mContent;

        #region Properties
        /// <summary>
        /// Gets or set the request object used.
        /// </summary>
        public HttpWebRequest Request
        {
            get { return mRequest; }
            set { mRequest = value; }
        }

        /// <summary>
        /// Gets or set the body of the http request (only available for POST requests). 
        /// </summary>
        public String Content
        {
            get { return mContent; }
            set { mContent = value; }
        }
        #endregion

        /// <summary>
        /// Creates a new http web request action item based on an existing web definition.
        /// </summary>
        /// <param name="rawRequest"></param>
        public ActionItem_HttpRequest(ActionItem_WebRequest rawRequest)
        {
            mContent = rawRequest.Content;

            mRequest = (HttpWebRequest)WebRequest.Create(rawRequest.Uri);
            mRequest.Method = rawRequest.Method;
            mRequest.ProtocolVersion = rawRequest.HttpVersion.Equals("1.1") ? HttpVersion.Version11 : HttpVersion.Version10;
            mRequest.AllowAutoRedirect = false;
            foreach (KeyValuePair<String, String> head in rawRequest.Headers)
            {
                if (head.Key.ToLower().Equals("accept"))
                    mRequest.Accept = head.Value;
                else if (head.Key.ToLower().Equals("connection"))
                    if (head.Value.ToLower().Equals("keep-alive"))
                        mRequest.KeepAlive = true;
                    else if (head.Value.ToLower().Equals("close"))
                        mRequest.KeepAlive = false;
                    else
                        mRequest.Connection = head.Value;
                else if (head.Key.ToLower().Equals("content-length"))
                    mRequest.ContentLength = Convert.ToInt64(head.Value);
                else if (head.Key.ToLower().Equals("content-type"))
                    mRequest.ContentType = head.Value;
                else if (head.Key.ToLower().Equals("expect")) { }
                else if (head.Key.ToLower().Equals("date")) { }
                else if (head.Key.ToLower().Equals("host"))
                    mRequest.Host = head.Value;
                else if (head.Key.ToLower().Equals("if-modified-since")) { }
                else if (head.Key.ToLower().Equals("range")) { }
                else if (head.Key.ToLower().Equals("referer"))
                    mRequest.Referer = head.Value;
                else if (head.Key.ToLower().Equals("user-agent"))
                    mRequest.UserAgent = head.Value;
                else
                    mRequest.Headers.Add(head.Key, head.Value);
            }
        }
    }
    
    [Serializable()]
    public class ActionItemCollection
        : IList<IActionItem>, ICollection<IActionItem>, IEnumerable<IActionItem>, ISerializable
    {
        public IEnumerator<IActionItem> GetEnumerator() { return mActions.GetEnumerator(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return mActions.GetEnumerator(); }

        public ActionItemCollection(SerializationInfo info, StreamingContext ctxt)
        {
            mActions = (List<IActionItem>)info.GetValue("Actions", typeof(List<IActionItem>));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Actions", mActions);
        }

        List<IActionItem> mActions = new List<IActionItem> { };

        public ActionItemCollection() { }

        public int Count { get { return mActions.Count; } }

        public bool IsReadOnly { get { return false; } }

        public IActionItem this[int index] { get { return mActions[index]; } set { mActions[index] = value; } }

        public IActionItem this[string name]
        {
            get
            {
                foreach (IActionItem rdef in mActions)
                    if (rdef.Name.Equals(name))
                        return rdef;
                return null;
            }
            set
            {
                for (int i = 0; i < mActions.Count; i++)
                    if (mActions[i].Name.Equals(name))
                        mActions[i] = value;
            }
        }

        public void Add(IActionItem item) { mActions.Add(item); }

        public void AddRange(IEnumerable<IActionItem> collection) { mActions.AddRange(collection); }

        public void Clear() { mActions.Clear(); }

        public bool Contains(IActionItem item) { return mActions.Contains(item); }

        public bool Contains(IActionItem value, IEqualityComparer<IActionItem> comparer) { return mActions.Contains(value, comparer); }

        public void CopyTo(IActionItem[] array, int arrayIndex) { mActions.CopyTo(array, arrayIndex); }

        public int IndexOf(IActionItem value) { return mActions.IndexOf(value); }

        public int IndexOf(string name) 
        {
            for (int i = 0; i < mActions.Count; i++)
                if (mActions[i].Name.Equals(name)) { return i; }
            return -1; 
        }

        public void Insert(int index, IActionItem value) { mActions.Insert(index, value); }

        public bool Remove(IActionItem value) { return mActions.Remove(value); }

        public bool Remove(string name) 
        {
            for (int i = 0; i < mActions.Count; i++)
                if (mActions[i].Name.Equals(name)) { RemoveAt(i); return true; }
            return false; 
        }

        public void RemoveAt(int index) { mActions.RemoveAt(index); }

        /// <summary>
        /// Moves the item at index up the order (index 1 will become 0).
        /// </summary>
        /// <param name="index"></param>
        public void MoveUp(int index)
        {
            if (index < 0 || index >= mActions.Count)
                throw new IndexOutOfRangeException();
            if (index == 0)
                return;
            IActionItem tmp = mActions[index - 1];
            mActions[index - 1] = mActions[index];
            mActions[index] = tmp;
        }
        /// <summary>
        /// Moves the item at index down the order (index 1 will become 2).
        /// </summary>
        /// <param name="index"></param>
        public void MoveDown(int index)
        {
            if (index < 0 || index >= mActions.Count)
                throw new IndexOutOfRangeException();
            if (index == mActions.Count - 1)
                return;
            IActionItem tmp = mActions[index + 1];
            mActions[index + 1] = mActions[index];
            mActions[index] = tmp;
        }

        public IActionItem[] GetScriptActions(bool recursive = true)
        {
            List<IActionItem> list = new List<IActionItem>{};
            for (int i = 0; i < mActions.Count; i++)
            {
                switch (mActions[i].ActionType)
                {
                    case ActionType.Script:
                    case ActionType.Variable:
                        list.Add(mActions[i]);
                        break;
                    case ActionType.If:
                        list.Add(mActions[i]);
                        if (recursive)
                        {
                            list.AddRange(((ActionItem_If)mActions[i]).ThenActions.GetScriptActions());
                            list.AddRange(((ActionItem_If)mActions[i]).ElseActions.GetScriptActions());
                        }
                        break;
                    case ActionType.Loop:
                        if (recursive)
                            list.AddRange(((ActionItem_Loop)mActions[i]).Actions.GetScriptActions());
                        break;
                    default:
                        break;
                }
            }
            return list.ToArray();
        }
    }

    [Serializable()]
    public class ActionResults
    {
        TimeSpan mDuration;
        List<string> mErrors;
        List<string> mWarnings;
        List<object> mData;

        public TimeSpan Duration { get { return mDuration; } set { mDuration = value; } }

        public bool HasErrors { get { return mErrors.Count > 0 ? true : false; } }
        public List<string> Errors { get { return mErrors; } }
        
        public bool HasWarnings { get { return mWarnings.Count > 0 ? true : false; } }
        public List<string> Warnings { get { return mWarnings; } }

        public List<object> Data { get { return mData; } }

        public ActionResults() : this(TimeSpan.Zero, null, null, null) { }
        
        public ActionResults(TimeSpan duration) : this (duration, null, null, null) { }

        public ActionResults(TimeSpan duration, object[] data) : this(duration, null, null, data) { }

        public ActionResults(TimeSpan duration, string[] errors, string[] warnings, object[] data) 
        {
            mDuration = duration;
            mErrors = new List<string> { };
            mWarnings = new List<string> { };
            mData = new List<object> { };
            if (errors != null)
                mErrors.AddRange(errors);
            if (warnings != null)
                mWarnings.AddRange(warnings);
            if (data != null)
                mData.AddRange(data);
        }

        public ActionResults(SerializationInfo info, StreamingContext ctxt)
        {
            mDuration = (TimeSpan)info.GetValue("Duration", typeof(TimeSpan));
            mErrors = (List<string>)info.GetValue("Errors", typeof(List<string>));
            mWarnings = (List<string>)info.GetValue("Warnings", typeof(List<string>));
            mData = (List<object>)info.GetValue("Data", typeof(List<object>)); 
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Duration", mDuration);
            info.AddValue("Errors", mErrors);
            info.AddValue("Warnings", mWarnings);
            info.AddValue("Data", mData);
        }
    }
}
*/